import { ObjectId } from "mongodb";
import { MongodbClient } from "../lib/db.client.mongodb";
import { PgClient } from "../lib/db.client.pg";

import { Contact, ContactGroup, User } from "qqlx-core";
import { getConditionMatchStr, ContactGroupSchema, ContactSchema } from "qqlx-cdk";

import { User as OldUser, UserWeChat as OldUserWeChat } from "../../../qqlx.old/qqlx-core";
import { Corp as OldCorp } from "../../../qqlx.old/qqlx-core";
import { ENUM_CONTACT, Contact as OldContact } from "../../../qqlx.old/qqlx-core";

import { ContactGroupDao, ContactDao } from "../dao/pond";

export async function doContactInsert(corpId: string, user_old_new_map: Map<OldUser["_id"], User>) {
  const mongodbClient = new MongodbClient("mongodb://localhost:27017/qqlx");
  const pgClient = new PgClient("127.0.0.1", "5432", "production", "postgres", "postgres");
  const _id_to_contact_map = new Map<OldContact["_id"], Contact>();

  console.group("\n开始迁移mongo联系人数据");
  const stat = { before: 0, wanner: 0, now: 0 };

  try {
    await mongodbClient.start();

    const colCorps = mongodbClient.getCollection("corps");
    const corpExist = (await colCorps.findOne<OldCorp>({ _id: corpId as unknown as ObjectId })) as OldCorp;
    const corpQuery = { corpId: corpExist._id as unknown as ObjectId };

    const colContacts = mongodbClient.getCollection("contacts");
    const mongo_contact_list = await colContacts.find<OldContact>(corpQuery).toArray();
    stat.wanner = mongo_contact_list.length;

    // ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░░░░▄▄▄▄▄▄░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░░▄█▀▀▀▀▀█▄░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░▄█░░▄▄▄░░█▄░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░█░░█▀▀█░░█░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░█░░█▀▀█░░█░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░█░░█▄▄█░░█░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░▀▄▀▄▄▄▄▄▀▄▀░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░

    const pgClientIns = await pgClient.start();
    const contactGroupDao = new ContactGroupDao(pgClientIns.getRepository<ContactGroup>(ContactGroupSchema));
    const contactDao = new ContactDao(pgClientIns.getRepository<Contact>(ContactSchema));

    const master = user_old_new_map.get(corpExist.userId) as User;
    const condis = [getConditionMatchStr("refOwnerUUid32", master.uuid32)];
    const contactCount = await contactDao.count(condis);
    stat.before = contactCount;

    if (contactCount === 0) {
      const groupSale = await contactGroupDao.insertOne(getDefaultGroup(master.uuid32, "客户"));
      groupSale.sequence = 3;
      const groupPurchase = await contactGroupDao.insertOne(getDefaultGroup(master.uuid32, "供应商"));
      groupPurchase.sequence = 2;
      const groupOther = await contactGroupDao.insertOne(getDefaultGroup(master.uuid32, "其他"));
      groupOther.sequence = 1;

      const schemaLs: Contact[] = [];
      for (const old of mongo_contact_list) {
        if (old.type === ENUM_CONTACT.PURCHASE) {
          const schema = getDefaultContact(master.uuid32, groupPurchase.id, old);
          schemaLs.push(schema);
        } else if (old.type === ENUM_CONTACT.SALES) {
          const schema = getDefaultContact(master.uuid32, groupSale.id, old);
          schemaLs.push(schema);
        } else if (old.type === ENUM_CONTACT.NONE) {
          const schema = getDefaultContact(master.uuid32, groupOther.id, old);
          schemaLs.push(schema);
        }
      }
      await contactDao.insertMany(schemaLs);

      const emptyOne = new ContactSchema();
      emptyOne.refOwnerUUid32 = master.uuid32;
      emptyOne.refContactGroupId = groupOther.id;
      emptyOne.name = "未知联系人";
      emptyOne.desc = "Unknown";
      emptyOne.content = `${master.uuid32}:contact:unknown`; // 旧联系人的_id
      await contactDao.insertOne(emptyOne);
    }

    // 缓存数据
    const contactAll = await contactDao.queryAll(condis);
    contactAll.list.map((exist) => _id_to_contact_map.set(exist.content, exist));

    // ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░░░░▄▄▄▄▄▄░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░░▄█▀▀▀▀▀█▄░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░▄█░░▄▄▄░░█▄░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░█░░█▀▀█░░█░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░█░░█▀▀█░░█░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░█░░█▄▄█░░█░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░▀▄▀▄▄▄▄▄▀▄▀░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░

    const pgCountFinal = await contactDao.count(condis);
    stat.now = pgCountFinal;

    console.log(`🔴迁移前 >> 迁移后 / pond_contact`, stat.before, stat.now);
    console.log(`期望`, stat.wanner);
    console.log(`📉误差`, stat.now - stat.before - stat.wanner);
    console.groupEnd();
    console.log("====================================");
  } finally {
    await pgClient.stop();
    await mongodbClient.stop();
  }

  return { _id_to_contact_map };
}

function getDefaultGroup(masterId: string, name: string) {
  const schema: ContactGroup = new ContactGroupSchema();
  schema.refOwnerUUid32 = masterId;
  schema.name = name;
  return schema;
}

function getDefaultContact(masterId: string, groupId: ContactGroup["id"], entity: OldContact) {
  const schema: Contact = new ContactSchema();
  schema.timeCreate = entity.timeCreate.toString();
  schema.timeUpdate = entity.timeUpdate.toString();
  schema.refOwnerUUid32 = masterId;
  schema.refContactGroupId = groupId;

  schema.name = entity.name;
  schema.desc = entity.remark;
  schema.remark = entity.address;
  schema.isDisabled = entity.isDisabled;

  // 新系统中暂时还没有用，用来临时存放旧系统的id
  schema.content = entity._id;
  return schema;
}
